package com.hsmpay.mobile.action.account.externalAccessPay;

import com.hsmpay.common.pojo.qian4.Qian4SendLog;
import com.hsmpay.common.pojo.user.User;
import com.hsmpay.common.util.DateConvertUtil;
import com.hsmpay.common.util.NumberUtil;
import com.hsmpay.common.util.OrderTypeUtil;
import com.hsmpay.common.util.URLDecoderTools;
import com.hsmpay.mobile.action.account.qian48.Q4BaseAction;
import com.hsmpay.mobile.action.account.scanCodePay.ScanCodePayParam;
import com.hsmpay.mobile.pojo.terminal.Tchannel;
import com.hsmpay.mobile.pojo.trans.TransOrder;
import com.hsmpay.mobile.pojo.trans.TransPriorSettle;
import com.hsmpay.mobile.service.trans.TransPriorSettleService;
import com.hsmpay.qian4.pojo.PurchaseResult;
import com.hsmpay.utils.TimeUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class ExternalAccessPayBaseAction extends Q4BaseAction {

    private static final long serialVersionUID = 4841990981226162770L;
    private static org.slf4j.Logger log = LoggerFactory.getLogger(ExternalAccessPayBaseAction.class);

    public static final String SCANCODEPAY_FUNCKEY = "EXTERNAL_ACCESS_PAY_INTERFACE";

    protected String version; //版本号
    protected String service; //接口类型
    protected String reqDate; //请求日期,格式yyyyMMdd
    protected String transAmount; //订单总金额，单位为“分”，只能整数
    protected String bgReturnUrl; //回调地址
    protected String customerNo; //商户号
    protected String externalId; //商户系统内部的订单号,20个字符内可包含字母, 确保在商户系统唯一
    protected String selfData; //自定义数据
    protected String openId;
    protected String requestIp; //请求IP
    protected String description; //要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
    protected String reqTime; //请求时间,格式HHmmss
    protected String appClient; //请求App 1支付宝 2微信

    @Resource(name = "transPriorSettleService")
    public TransPriorSettleService<TransPriorSettle, Long> transPriorSettleService;

    protected Object[] assembleBean(User user) throws Exception {
        clientType = user.getClientType();
        terminalTypeId = user.getTerminalTypeId();
        roleId = user.getRoleId();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        merchantOrderTime = sdf.format(new Date());
        functionKey = SCANCODEPAY_FUNCKEY;


        //查出商户订单号 是否存在
        TransOrder transOrder = transOrderService.searchOrderByMerAndUserId(user.getId(), externalId);
        if (null != transOrder) {
            log.info("商户订单号："+externalId+" 已存在，不支持重复交易！");
            sendThirdErrorMsg("6101", "商户订单号:"+externalId+"已存在,不支持重复交易!");
            return null;
        }

        //校验IP
//        String remoteIp = URLDecoderTools.getRemoteHost(getRequest());
//        if(!remoteIp.equals(requestIp)){
//            log.info("remoteIp: " + remoteIp + " requestIp: " + requestIp + " IP未注册");
//            sendThirdErrorMsg("6001", "IP未注册");
//            return null;
//        }

        //组装 发送数据
        Qian4SendLog send = new Qian4SendLog();
        Date date = new Date();
        send.setCallType(0);
        send.setUserId(user.getId());
        send.setOrderTypeId(RECEIVABLES);
        send.setApplication("externalAccessPay.Req");
        send.setTransType("100001");//
        send.setSendTime(date);
        send.setSendSeqId(TimeUtils.getTimeToString());
        send.setMerchantId(user.getJQCusId());
        send.setPlatformId(platformId);
        send.setRoleId(user.getRoleId());
        send.setMerchantOrderId(externalId);//商户订单号
        send.setMerchantOrderTime(DateConvertUtil.stringDate(reqDate + reqTime, "yyyyMMddHHmmss"));//商户订单号时间
        send.setTransTime(send.getSendTime());
        send.setTransAmt(String.valueOf(NumberUtil.roundF2(Double.valueOf(transAmount)/100)));
        send.setCurrency("156");
        send.setIp(URLDecoderTools.getRemoteHost(getRequest()));//IP
        send.setCardTypeN(4);
        send.setCollectionType(user.getChannelId().intValue());
        send.setServiceInfo(service);
        send.setSenderSign(version);

        transOrder = new TransOrder();
        transOrder.setOrderNum(genOrderNo(user.getChannelId()));
        transOrder.setOrderTypeId(RECEIVABLES);//我要收款
        transOrder.setUserId(user.getId());
        transOrder.setPUserId(user.getPUserId());//父用户Id
        transOrder.setTransMoney(NumberUtil.roundF2(Double.valueOf(transAmount)/100));
        transOrder.setRootCategory("账务管理");
        transOrder.setCategory(OrderTypeUtil.RECEIVABLES_STR);
        transOrder.setObjectiveName(StringUtils.isBlank(user.getCardholder()) ? user.getUserName() : user.getCardholder());//user.getUserName());//对方持卡人姓名
        transOrder.setStatus(3);//交易状态  0交易失败 1交易成功 2银行交易处理中 3 未付款 4等待对方付款 5关闭交易
        transOrder.setClearing(0);//结算状态 0未结算 1结算
        transOrder.setCreateDate(date);
        transOrder.setUpdateLongTime(date.getTime());

        transOrder.setObjectiveBBank(user.getBranchesBank());//对方银行支行
        transOrder.setObjectiveBBProvince(user.getBBankProvince());
        transOrder.setObjectiveBBCity(user.getBBankCity());
        transOrder.setObjectiveMobile(user.getMobile());//对方手机号
        transOrder.setObjectiveBBankCode(user.getBranchesBankCode());//支行Code
        transOrder.setTerminalTypeId(user.getTerminalTypeId());
        transOrder.setRoleId(user.getRoleId());
        transOrder.setCardTypeN(send.getCardTypeN());//1 磁条卡 2 IC卡 3无卡 4扫码
        transOrder.setClientType(user.getClientType());
        transOrder.setFeeRate(user.getFeeRate());//用户费率
        transOrder.setOtherData(bgReturnUrl);
        send.setBankOrderNum(transOrder.getOrderNum());

        ScanCodePayParam scanCodePayParam = new ScanCodePayParam();
        scanCodePayParam.setBody(user.getNickName());
        scanCodePayParam.setAttach(externalId);
        scanCodePayParam.setOutTradeNo(transOrder.getOrderNum());
        scanCodePayParam.setTotalFee(String.valueOf(NumberUtil.roundF2(Double.valueOf(transAmount)/100)));
        scanCodePayParam.setSpBillCreateIP(requestIp);
        scanCodePayParam.setGoodsTag(description);
        scanCodePayParam.setOpenId(openId);
        scanCodePayParam.setSubOpenId(openId);
        scanCodePayParam.setAppClient(appClient);

        Object[] resultA = new Object[3];
        resultA[0] = send;
        resultA[1] = transOrder;
        resultA[2] = scanCodePayParam;
        return resultA;
    }

    /**
     * 返回
     * @param pr
     * @param transOrder
     * @param transPriorSettle
     * @param user
     * @param tc
     * @return
     * @throws Exception
     */
    protected JSONObject purchaseResolveResult(Qian4SendLog send, PurchaseResult pr, TransOrder transOrder, TransPriorSettle transPriorSettle, User user, Tchannel tc) throws Exception {
        JSONObject result = new JSONObject();
        if (0 == pr.getStatus()) {//错误
            log.debug("交易失败!");
            result.put("code", pr.getReqCode());
            result.put("message", pr.getReqMsg());
            accountManageQ4Service.receivablesError(transPriorSettle, pr.getReqCode(), pr.getReqMsg());
            qian4SendLogService.updateResCodeMassage(transPriorSettle.getSendId(), pr.getReqCode(), pr.getReqMsg());
        } else {
            accountManageQ4Service.purchaseResolveResult(transPriorSettle, send, pr, tc, user.getOrganizationId());
            result.put("code", pr.getReqCode());
            result.put("message", pr.getReqMsg());
        }
        return result;
    }

    /**
     * 撤销超时
     * @return
     * @throws Exception
     */
    public Map<String, Object> revocationOrderTimeOut(Qian4SendLog recSend, TransPriorSettle transPriorSettle, ScanCodePayParam scanCodePayParam){

        Date date = new Date();
        Qian4SendLog send = new Qian4SendLog();
        send.setCallType(0);
        send.setUserId(recSend.getUserId());
        send.setApplication("Void.Req");
        send.setOrderTypeId(OrderTypeUtil.REVOCATION);
        send.setSendTime(date);
        send.setRoleId(recSend.getRoleId());
        send.setSendSeqId(TimeUtils.getTimeToString());
        send.setTransType("200000");//200000：撤销

        send.setMerchantOrderId(DateConvertUtil.dateString(date, "yyyyMMddHHmmssSSS"));
        send.setMerchantOrderTime(DateConvertUtil.stringDate(merchantOrderTime, "yyyyMMddHHmmss"));
        send.setTransTime(send.getSendTime());
        send.setOrgTransId(recSend.getBankOrderNum());//原订单号
        send.setOrgTransTime(recSend.getMerchantOrderTime());//原订单时间
        send.setOrgMerchantOrderId(recSend.getMerchantOrderId());
        send.setTransAmt(recSend.getTransAmt());

        send.setMerchantSign(recSend.getMerchantSign());
        send.setSenderSign(recSend.getSenderSign());
        send.setServiceInfo(recSend.getServiceInfo());
        send.setTerminalInfo(recSend.getTerminalInfo());

        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("status", 0);
        try {
            resultMap = accountManageQ4Service.isCanRevocationOrder(send);
            int status = (Integer) resultMap.get("status");
            if (status == 1) {
                TransOrder transOrder = new TransOrder();
                transOrder.setOrderNum(transPriorSettle.getOrderNum());
                transOrder = transOrderService.searchEntity(transOrder);
                if (transOrder.getStatus().intValue() == 1) {
                    if (null != transPriorSettle.getStatus() && 1 == transPriorSettle.getStatus().intValue()) {
                        //查询订单 修改金额
                        accountManageQ4Service.updateUserMoney(transOrder, 0, transOrder.getChargeAmount());
                    }
                }
                transOrderService.updateStatusClearing(transPriorSettle.getOrderNum(), 7, null);//发起撤销
                transPriorSettle = transPriorSettleService.searchTransPriorSettle(send.getTerminalId(), send.getOrgMerchantOrderId());
                date = new Date();
                send.setMerchantOrderId(DateConvertUtil.dateString(date, "yyyyMMddHHmmssSSS"));
                send.setMerchantOrderTime(date);
                long sendId = qian4SendLogService.insertEntity(send);
                send.setId(sendId);
                //真正去冲正的方法
                resultMap = accountManageQ4Service.scanRevocationOrder(send,scanCodePayParam);
                int flag = (Integer) resultMap.get("status");
                if (flag == 0 && (send.timeOut == 1 || send.timeOut == 2 || send.timeOut == 3)) {
                    resultMap = revocationOrderTimeOut(recSend, transPriorSettle,scanCodePayParam);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultMap;
    }

    //----------------------------------------getter and setter-------------------------------------


    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getService() {
        return service;
    }

    public void setService(String service) {
        this.service = service;
    }

    public String getReqDate() {
        return reqDate;
    }

    public void setReqDate(String reqDate) {
        this.reqDate = reqDate;
    }

    public String getTransAmount() {
        return transAmount;
    }

    public void setTransAmount(String transAmount) {
        this.transAmount = transAmount;
    }

    public String getBgReturnUrl() {
        return bgReturnUrl;
    }

    public void setBgReturnUrl(String bgReturnUrl) {
        this.bgReturnUrl = bgReturnUrl;
    }

    public String getCustomerNo() {
        return customerNo;
    }

    public void setCustomerNo(String customerNo) {
        this.customerNo = customerNo;
    }

    public String getExternalId() {
        return externalId;
    }

    public void setExternalId(String externalId) {
        this.externalId = externalId;
    }

    public String getSelfData() {
        return selfData;
    }

    public void setSelfData(String selfData) {
        this.selfData = selfData;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getRequestIp() {
        return requestIp;
    }

    public void setRequestIp(String requestIp) {
        this.requestIp = requestIp;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getReqTime() {
        return reqTime;
    }

    public void setReqTime(String reqTime) {
        this.reqTime = reqTime;
    }

    public String getAppClient() {
        return appClient;
    }

    public void setAppClient(String appClient) {
        this.appClient = appClient;
    }
}
